/*****************************************************************************
 *                                McPAT/CACTI
 *                      SOFTWARE LICENSE AGREEMENT
 *            Copyright 2012 Hewlett-Packard Development Company, L.P.
 *                          All Rights Reserved
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.

 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.”
 *
 ***************************************************************************/

#ifndef __BASIC_CIRCUIT_H__
#define __BASIC_CIRCUIT_H__

#include "cacti_interface.h"
#include "const.h"

using namespace std;

#define UNI_LEAK_STACK_FACTOR 0.43

int powers(int base, int n);
bool is_pow2(int64_t val);
uint32_t _log2(uint64_t num);
int factorial(int n, int m = 1);
int combination(int n, int m);

//#define DBG
#ifdef DBG
#define PRINTDW(a) \
  ;                \
  a;
#else
#define PRINTDW(a) ;

#endif

enum Wire_placement { outside_mat, inside_mat, local_wires };

enum Htree_type {
  Add_htree,
  Data_in_htree,
  Data_out_htree,
  Search_in_htree,
  Search_out_htree,
};

enum Gate_type { nmos, pmos, inv, nand, nor, tri, tg };

enum Half_net_topology { parallel, series };

double logtwo(double x);

double gate_C(double width, double wirelength, bool _is_dram = false,
              bool _is_sram = false, bool _is_wl_tr = false,
              bool _is_sleep_tx = false);

double gate_C_pass(double width, double wirelength, bool _is_dram = false,
                   bool _is_sram = false, bool _is_wl_tr = false,
                   bool _is_sleep_tx = false);

double drain_C_(double width, int nchannel, int stack,
                int next_arg_thresh_folding_width_or_height_cell,
                double fold_dimension, bool _is_dram = false,
                bool _is_sram = false, bool _is_wl_tr = false,
                bool _is_sleep_tx = false);

double tr_R_on(double width, int nchannel, int stack, bool _is_dram = false,
               bool _is_sram = false, bool _is_wl_tr = false,
               bool _is_sleep_tx = false);

double R_to_w(double res, int nchannel, bool _is_dram = false,
              bool _is_sram = false, bool _is_wl_tr = false,
              bool _is_sleep_tx = false);

double horowitz(double inputramptime, double tf, double vs1, double vs2,
                int rise);

double pmos_to_nmos_sz_ratio(bool _is_dram = false, bool _is_wl_tr = false,
                             bool _is_sleep_tx = false);

double simplified_nmos_leakage(double nwidth, bool _is_dram = false,
                               bool _is_cell = false, bool _is_wl_tr = false,
                               bool _is_sleep_tx = false);

double simplified_pmos_leakage(double pwidth, bool _is_dram = false,
                               bool _is_cell = false, bool _is_wl_tr = false,
                               bool _is_sleep_tx = false);

double simplified_nmos_Isat(double nwidth, bool _is_dram = false,
                            bool _is_cell = false, bool _is_wl_tr = false,
                            bool _is_sleep_tx = false);

double simplified_pmos_Isat(double pwidth, bool _is_dram = false,
                            bool _is_cell = false, bool _is_wl_tr = false,
                            bool _is_sleep_tx = false);

double cmos_Ileak(double nWidth, double pWidth, bool _is_dram = false,
                  bool _is_cell = false, bool _is_wl_tr = false,
                  bool _is_sleep_tx = false);

double cmos_Ig_n(double nWidth, bool _is_dram = false, bool _is_cell = false,
                 bool _is_wl_tr = false, bool _is_sleep_tx = false);

double cmos_Ig_p(double pWidth, bool _is_dram = false, bool _is_cell = false,
                 bool _is_wl_tr = false, bool _is_sleep_tx = false);

double cmos_Isub_leakage(double nWidth, double pWidth, int fanin,
                         enum Gate_type g_type, bool _is_dram = false,
                         bool _is_cell = false, bool _is_wl_tr = false,
                         bool _is_sleep_tx = false,
                         enum Half_net_topology topo = series);

double cmos_Ig_leakage(double nWidth, double pWidth, int fanin,
                       enum Gate_type g_type, bool _is_dram = false,
                       bool _is_cell = false, bool _is_wl_tr = false,
                       bool _is_sleep_tx = false,
                       enum Half_net_topology topo = series);

double shortcircuit(double vt, double velocity_index, double c_in, double c_out,
                    double w_nmos, double w_pmos, double i_on_n, double i_on_p,
                    double i_on_n_in, double i_on_p_in, double vdd);

double shortcircuit_simple(double vt, double velocity_index, double c_in,
                           double c_out, double w_nmos, double w_pmos,
                           double i_on_n, double i_on_p, double i_on_n_in,
                           double i_on_p_in, double vdd);
// set power point product mask; strictly speaking this is not real point
// product
inline void set_pppm(double *pppv, double a = 1, double b = 1, double c = 1,
                     double d = 1) {
  pppv[0] = a;
  pppv[1] = b;
  pppv[2] = c;
  pppv[3] = d;
}

inline void set_sppm(double *sppv, double a = 1, double b = 1, double c = 1,
                     double = 1) {
  sppv[0] = a;
  sppv[1] = b;
  sppv[2] = c;
}

#endif
